以前的我,會把「功能做完」理解得很直接。
畫面有出來、按鈕有反應、資料看起來也正常,我就會覺得這件事差不多可以告一段落了。
那時候我知道有 Git、branch、PR 這些東西,但它們在我心裡比較像是一串分開的步驟:要做功能時開一個 branch,寫完後送出去,之後再把它合進去。
做到後來,再回頭看 PawPal 的整個開發流程,我才發現自己一開始其實只看見了中間那一段。
真正的開發不是從打開編輯器才開始,也不是按下 commit 後就結束。
它比較像是一條一路往前、又不斷確認方向的路:先弄懂問題,再決定範圍;把修改放進自己的 branch;完成自己的部分後交給團隊檢視;合併後確認沒有影響其他地方;部署之後,再到正式環境真的操作一次。
這些事情以前我都聽過,但直到自己在團隊專案裡走過,才開始明白它們為什麼一個接著一個。
以前拿到一張票,我很容易先想:
「這個功能要怎麼寫?」
腦中很快就會出現畫面、元件或 API,然後想趕快開始。
剛開始做 PawPal 的時候,我也真的有一、兩次做到超出票原本的範圍。
當時其實沒有想太多,只是覺得既然都做到這裡了,那再多做一點好像也沒關係。看到什麼可以一起改,就順手一起處理。
後來被組長提醒之後,我才開始注意到:
做得比較多,不一定就代表做得比較對。
如果這張票原本只需要解決一個問題,我卻順便改了其他地方,不但增加修改範圍,也可能讓 Review 的人更難確認到底改了什麼,甚至影響原本沒有要動到的功能。
也是從那之後,我拿到票時會比較刻意先確認這次到底要處理到哪裡。
現在我會先問自己幾個問題:
所以現在拿到一張票時,我會提醒自己:
先不要急著寫,先搞清楚這張票為什麼要做。
在 PawPal 的專案紀錄裡,有一張針對手機版醫院卡片與地圖互動的需求。
裡面不只是寫「手機版要改」,而是把使用者點擊卡片之後應該發生什麼事、畫面要怎麼移動,以及預期看到的結果都列了出來。
回頭看這類 Issue,我才更具體地理解:
Issue 不是只有一句「今天要做什麼」。
它也是團隊拿來對齊問題、範圍,以及做到哪裡才算完成的地方。
這不代表每一張票一開始就能把所有答案寫得很完整,但至少在動手之前,我應該先知道自己正在解決什麼問題。
我以前知道要開自己的 branch,卻沒有真正理解它和團隊的關係。
後來我才明白,branch 的目的不是讓我把功能藏在自己的世界裡慢慢做,而是讓這次修改有一個可以被追蹤、被討論,也能安全整合的位置。
因為專案一直在前進,別人也可能同時修改其他功能,甚至剛好改到同一個檔案。
所以我不能只盯著:
「我的畫面現在有沒有正常?」
我對 conflict 的印象很深。
第一次遇到時,我最怕的事情就是:
如果我選錯了,會不會把別人的程式蓋掉?
那種不確定感,讓我開始知道 Git 並不只是把程式碼「上傳」而已。
後來處理過幾次之後,我開始知道,看到兩邊都有修改時,重點不是急著決定要留下哪一邊,而是先理解雙方各自在處理什麼。
兩邊分別在處理什麼?
為什麼會同時改到這裡?
哪些內容需要保留?
我不需要把每一次衝突都變成一套 Git 操作教學,但我確實從 Conflict 裡學到一件事:
整合不是最後按一下按鈕,而是先理解彼此的修改,再決定怎麼讓它們一起存在。
過去我會覺得,只要自己測過、看起來沒問題,功能大概就完成了。
但 PR 讓我重新認識「完成」這兩個字。
當修改進到 PR,團隊才真正有機會看見我改了什麼、改動的範圍在哪裡,以及這些修改會不會影響其他功能。
Review 讓其他人有機會從不同角度檢查這次修改,也讓我看到一些自己一直盯著同一段程式時沒有注意到的地方。
我回頭看 PawPal 一段手機版互動功能的紀錄時,可以看到:
需求、功能 branch、數個 commits、PR、Review、核准,最後再 Merge 回團隊主要開發分支。
以前我可能只會注意「功能最後有沒有做出來」。
現在再看,我反而會注意中間這些紀錄。
因為一個功能要真正進入團隊的系統之前,不只是我自己覺得可以,而是還需要讓其他人知道這次改了什麼、確認修改範圍,也可能在整合過程中繼續調整。
所以現在送 PR 前,我會更在意幾件事:
這次到底改了哪些地方?
範圍有沒有不小心越變越大?
我有沒有先做過必要確認?
別人看到這個 PR 時,能不能理解我想解決什麼?
自己的功能能跑,和團隊能安心把它合進去,是兩件不同的事。
以前我把 Merge 想得很像終點。
功能合進去了,我就會覺得:
「好,這張票完成了。」
現在我比較把 Merge 看成一個交接點。
因為當自己的程式碼真的和其他人的修改放在一起之後,才更需要確認它們能不能一起運作。
這也是我開始把測試、部署和正式環境確認放進「完成」定義裡的原因。
做到專案後期,我也開始注意到,團隊的流程裡不只有開發和 Merge,後面還有測試與建置。
這些東西不是要讓我把測試流程全部背起來,而是在提醒我:
確認一個功能不能只靠一句「我覺得可以」。
寫完之後,還需要再驗證。
部署也是一樣。
我以前對部署的理解其實很簡單:
把網站放到公開的網域上,讓別人可以打開。
真正做過之後,才發現公開網址能打開只是下一個確認的開始。
前端和後端 API 有沒有正常連線、本機和正式環境有沒有差異、不同網址進入頁面時有沒有問題,這些事情都可能在部署後才真的看見。
所以現在的我不會只停在:
「程式碼已經 Merge 了。」
而是會繼續往後想:
測試有沒有問題?
部署後有沒有正常?
真的用正式網址操作時,使用者走的流程是不是也沒有問題?
如果要用一句話整理 Day 28 的學習,那就是:
功能寫完,不代表真的完成。
現在我心裡的「完成」,比以前多了很多層。
簡化概念:
理解需求
↓
確認範圍與完成條件
↓
建立 Branch
↓
開發
↓
Commit
↓
PR / Review
↓
修改
↓
Merge
↓
測試
↓
部署
↓
正式環境確認
這不是一份要我死背的 SOP,也不是每一張票都一定會完全照這個順序進行。
它比較像是一個提醒。
我做的每一個功能,都不是只屬於我眼前那個畫面。
它最後會進到一個有人協作、有人使用,也需要被持續維護的系統裡。
現在如果重新拿到一張票,我還是會有想趕快開始做的時候,但至少我會先提醒自己:
先確認問題。
先確認範圍。
不確定就問。
PR 前自己先看一次改了什麼。
遇到 Conflict,不要急著決定哪一邊要留下。
Merge 之後,也不要馬上覺得工作已經結束。
我也還在學習怎麼把這條流程走得更穩。
但跟剛開始做 PawPal 時相比,我最大的差別可能不是 Git 指令記得比較多,也不是寫功能的速度變得多快。
而是我開始知道,在真正開始寫程式之前,其實還有一件更重要的事:
先理解自己到底要解決什麼問題。
先不要急著寫,先搞清楚這張票為什麼要做。
不懂就問,不要自己猜了半天最後才發現方向錯。
這是我從「急著把功能做出來」,慢慢走到「理解自己正在把什麼交給團隊」之後,最想留給自己的一段提醒。
走到這裡,我開始更清楚,自己在專案流程裡學到的不只是工具和步驟,也包含看待問題、和團隊協作,以及面對未知時的方式。
下一篇,我想把視角從 PawPal 的專案流程再拉遠一點,回頭看看這 30 天裡,自己的技術、想法和做事方式到底有哪些改變。
下一篇:
Day 29|這 30 天,我從一個新手變成了什麼樣的人?